package com.dayuanit.dy14.alipay.alipayspringbootstarter.auto.handler;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.dayuanit.dy14.alipay.alipayspringbootstarter.auto.config.NotifyInfoDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;

import java.util.Map;

/**
 *  处理支付宝支付、异步通知、订单查询功能。
 */
public class AlipayHandler implements InitializingBean, BeanNameAware {

    private static final Logger logger = LoggerFactory.getLogger(AlipayHandler.class);

    /**
     *
     */
    private String appId;
    private String merchantPrivateKey;
    private String aliPublicKey;
    private String format;
    private String charset;
    private String signType;
    private String payGateWay;
    private String notfiyUrl;
    private String returnUrl;
    private String producCode;
    private String subject;

    private static final String TRADE_SUCCESS = "TRADE_SUCCESS";
    private static final String TRADE_FINISHED = "TRADE_FINISHED";

    private AlipayClient alipayClient;

    /**
     * 如果想要在对象创建好之后 做一些事情 千万不能在构造方法里写，因为此时成员变量木有值
     * 建议使用spring bean的声明周期接口InitializingBean，实现里面的afterPropertiesSet方法，
     * 这样就能获取成员变量的值。
     */
    public AlipayHandler() {
    }


    @Override
    public void setBeanName(String s) {
        logger.info(">>>>>>beanName={}", s);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        logger.info(">>>>>>>>>>>merchantPrivateKey={}", merchantPrivateKey);
        logger.info(">>>>>>>>>>>appId={}", appId);
        logger.info(">>>>>>>>>>>notfiyUrl={}", notfiyUrl);

        alipayClient = new DefaultAlipayClient(payGateWay,
                appId,merchantPrivateKey,format,
                charset,aliPublicKey,signType);
    }

    /**
     * 创建支付宝 请求的form表单
     * @param bizOrderId 商户订单ID
     * @param amount 订单金额 单位：元
     * @return  form表单
     */
    public String createPayRequest(String bizOrderId, String amount) {

        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setNotifyUrl(notfiyUrl);
        request.setReturnUrl(returnUrl);

        request.setBizContent("{" +
                "\"out_trade_no\":\""+bizOrderId+"\"," +
                "\"product_code\":\""+producCode+"\"," +
                "\"total_amount\":\""+amount+"\"," +
                "\"subject\":\""+subject+"\"" +
                "  }");
        AlipayTradePagePayResponse response = null;
        String form = "";
        try {
            response = alipayClient.pageExecute(request);
            if(response.isSuccess()){
                logger.info("调用成功");
                form = response.getBody();
            } else {
                logger.info("调用失败");
            }
        } catch (AlipayApiException e) {
            logger.error(e.getErrMsg(), e);
        }

        logger.info("form表单={}", form);
        return form;
    }

    public NotifyInfoDTO checkNotify(Map<String, String> paramMap) {
        NotifyInfoDTO notifyInfoDTO = new NotifyInfoDTO();

        try {
            //验证签名 为了证明此异步请求是支付宝发送的 原理就是支付宝的私钥签名，只有支付宝的公钥才能解开
            boolean signVerified = AlipaySignature.rsaCheckV1(paramMap, aliPublicKey, charset, signType); //调用SDK验证签名
            if (!signVerified) {
                notifyInfoDTO.setSuccess(false);
                return notifyInfoDTO;
            }

            String bizOrderId = paramMap.get("out_trade_no");
            String tradeStatus = paramMap.get("trade_status");
            String totalAmount = paramMap.get("total_amount");

            if (!TRADE_SUCCESS.equals(tradeStatus) && !TRADE_FINISHED.equals(tradeStatus)) {
                notifyInfoDTO.setSuccess(false);
                return notifyInfoDTO;
            }

            if (!appId.equals(paramMap.get("app_id"))) {
                notifyInfoDTO.setSuccess(false);
                return notifyInfoDTO;
            }

            notifyInfoDTO.setBizOrderId(bizOrderId);
            notifyInfoDTO.setTotalAmount(totalAmount);
            notifyInfoDTO.setSuccess(true);
            return notifyInfoDTO;
        } catch (AlipayApiException e) {
            logger.error(e.getErrMsg(), e);
            notifyInfoDTO.setSuccess(false);
            return notifyInfoDTO;
        }
    }

    /**
     * 查询支付宝订单
     */
    public NotifyInfoDTO proceeQueryOrder(String bizOrderId) {
        NotifyInfoDTO notifyInfoDTO = new NotifyInfoDTO();

        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":\""+bizOrderId+"\"" +
                "  }");

        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if(!response.isSuccess()){
                logger.warn("商户订单{}支付宝订单查询失败", bizOrderId);
                notifyInfoDTO.setErrorMsg("订单查询失败");
                return notifyInfoDTO;
            }

            String tradeStatus = response.getTradeStatus();
            if (!"TRADE_SUCCESS".equals(tradeStatus) && !"TRADE_FINISHED".equals(tradeStatus)) {
                logger.warn("商户订单{}支付宝支付失败", bizOrderId);
                notifyInfoDTO.setErrorMsg("订单未支付");
                return notifyInfoDTO;
            }

            String totalAmount = response.getTotalAmount();

            notifyInfoDTO.setSuccess(true);
            notifyInfoDTO.setTotalAmount(totalAmount);
            notifyInfoDTO.setBizOrderId(bizOrderId);
            return notifyInfoDTO;

        } catch (AlipayApiException e) {
            logger.error(e.getErrMsg(), e);
            notifyInfoDTO.setErrorMsg(e.getErrMsg());
            return notifyInfoDTO;
        }

    }


    public void setAppId(String appId) {
        this.appId = appId;
    }

    public void setMerchantPrivateKey(String merchantPrivateKey) {
        this.merchantPrivateKey = merchantPrivateKey;
    }

    public void setAliPublicKey(String aliPublicKey) {
        this.aliPublicKey = aliPublicKey;
    }

    public void setFormat(String format) {
        this.format = format;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public void setSignType(String signType) {
        this.signType = signType;
    }

    public void setPayGateWay(String payGateWay) {
        this.payGateWay = payGateWay;
    }

    public void setNotfiyUrl(String notfiyUrl) {
        this.notfiyUrl = notfiyUrl;
    }

    public void setReturnUrl(String returnUrl) {
        this.returnUrl = returnUrl;
    }

    public void setProducCode(String producCode) {
        this.producCode = producCode;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }
}
